package com.hmall.item.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmall.api.dto.OrderDetailDTO;
import com.hmall.common.domain.PageDTO;
import com.hmall.common.exception.BizIllegalException;
import com.hmall.common.utils.BeanUtils;
import com.hmall.common.utils.CollUtils;
import com.hmall.item.domain.dto.ItemDTO;
import com.hmall.item.domain.po.Item;
import com.hmall.item.domain.query.ItemPageQuery;
import com.hmall.item.mapper.ItemMapper;
import com.hmall.item.service.IItemService;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 商品表 服务实现类
 * </p>
 *
 * @author itheima
 */
@Service
public class ItemServiceImpl extends ServiceImpl<ItemMapper, Item> implements IItemService {


    /**
     *  是给下单后 需要扣减库存调用
     * @param items
     */
    @Override
    public void deductStock(List<OrderDetailDTO> items) {
        String sqlStatement = "com.hmall.item.mapper.ItemMapper.updateStock";
        boolean r = false;
        try {
            r = executeBatch(items, (sqlSession, entity) -> sqlSession.update(sqlStatement, entity));
        } catch (Exception e) {
            log.error("更新库存异常", e);
//            return;
            throw new BizIllegalException("库存不足！");
        }
        if (!r) {
            throw new BizIllegalException("库存不足！");
        }
    }

    @Override
    public List<ItemDTO> queryItemByIds(Collection<Long> ids) {
        return BeanUtils.copyList(listByIds(ids), ItemDTO.class);
    }

    @Autowired
    @Qualifier("myRestHighLevelClient")
    private RestHighLevelClient client;

    /**
     * @param query
     * @return
     */
    @Override
    public PageDTO<ItemDTO> search(ItemPageQuery query) {
//        1. 构建查询请求
        SearchRequest request = new SearchRequest("items");
//        2. 设置查询条件： 搜索框、过滤栏
        // 复合查询条件
        BoolQueryBuilder boolQuery = new BoolQueryBuilder();
            //获得查询关键词
        String keyword = query.getKey();
        if (StrUtil.isNotBlank(keyword)){
            boolQuery.must(new MultiMatchQueryBuilder(keyword, "name", "brand"));
        } else {
            boolQuery.must(new MatchAllQueryBuilder());
        }

            //分类
        if (StrUtil.isNotBlank(query.getCategory())){
            boolQuery.filter(new TermQueryBuilder("category", query.getCategory()));
        }

            //品牌
        if (StrUtil.isNotBlank(query.getBrand())){
            boolQuery.filter(new TermQueryBuilder("brand", query.getBrand()));
        }

            //价格
        if (query.getMinPrice() != null &&  query.getMaxPrice() != null) {
            boolQuery.filter(new RangeQueryBuilder("price")
                    .lte(query.getMaxPrice()).gte(query.getMinPrice()));
        }

        request.source().query(boolQuery);
//        3. 设置分页
        request.source()
                .from((query.getPageNo() - 1) * query.getPageSize())
                .size(query.getPageSize());
//        4. 设置排序
        if (StrUtil.isNotBlank(query.getSortBy())){
            request.source().sort(query.getSortBy(), query.getIsAsc() ? SortOrder.ASC : SortOrder.DESC);
        }
//        5. 设置高亮
        request.source().highlighter(new HighlightBuilder()
                .field("name")
                .preTags("<em>")
                .postTags("</em>")
                .requireFieldMatch(false));
        try {
//        6. 发送请求
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
//        7. 处理返回结果
            long total = response.getHits().getTotalHits().value;
            long pages = total % query.getPageSize() == 0 ? (total / query.getPageSize()) : (total / query.getPageSize() + 1);

            // 当期页数据
            List<ItemDTO> itemDTOList =
                    Arrays.asList(response.getHits().getHits()).stream()
                            .map(e -> {
                                // 获取文档内容
                                ItemDTO itemDTO = JSONUtil.toBean(e.getSourceAsString(), ItemDTO.class);
                                // 处理高亮
                                Map<String, HighlightField> map = e.getHighlightFields();
                                if(CollUtils.isNotEmpty(map)) {
                                    HighlightField highlightField = map.get("name");
                                    if (highlightField != null) {
                                        itemDTO.setName(highlightField.getFragments()[0].toString());
                                    }
                                }
                                return itemDTO;
                            }).collect(Collectors.toList());
//        8. 返回结果

            return new PageDTO<>(total, pages, itemDTOList);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
}
